﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.model.Instance;
using MySql.Data.MySqlClient;
using System.Data;
using l1cs.server.utils;
using l1cs.server.templates;

namespace l1cs.server.datatables
{
    class CharacterItemsTable
    {
        private static Logger _log = Logger.getLogger( typeof( CharacterItemsTable ).FullName );

        /// <summary>
        /// プレイヤーの所持アイテムをDBから読み出す。
        /// </summary>
        /// <param name="objId">プレイヤーID</param>
        /// <returns>所持アイテムリスト</returns>
        public static List<L1ItemInstance> loadItems( int objId )
        {/*TTOK*/
            List<L1ItemInstance> items = new List<L1ItemInstance>();

            String sqlstr = "SELECT * FROM character_items WHERE char_id = ?1";
            using ( MySqlWrapper wrapper = new MySqlWrapper() )
            {
                MySqlCommand cmd = new MySqlCommand( sqlstr );
                cmd.Parameters.Add( "?1", MySqlDbType.Int24 ).Value = objId;
                DataTable dt = wrapper.GetDataTable( cmd );
                L1ItemInstance item;
                foreach ( DataRow dr in dt.Rows )
                {
                    int itemId = SqlUtils.toInt( dr["item_id"] );
                    L1Item itemTemplate = ItemTable.getInstance().getTemplate( itemId );
                    if ( itemTemplate == null )
                    {
                        _log.warning( String.Format( "item id:{0} not found", itemId ) );
                        continue;
                    }
                    item = new L1ItemInstance();
                    item.setId( SqlUtils.toInt( dr["id"] ) );
                    item.setItem( itemTemplate );
                    item.setCount( SqlUtils.toInt( dr["count"] ) );
                    item.setEquipped( SqlUtils.toBool( dr["Is_equipped"] ) );
                    item.setEnchantLevel( SqlUtils.toInt( dr["enchantlvl"] ) );
                    item.setIdentified( SqlUtils.toBool( dr["is_id"] ) );
                    item.set_durability( SqlUtils.toInt( dr["durability"] ) );
                    item.setChargeCount( SqlUtils.toInt( dr["charge_count"] ) );
                    item.setRemainingTime( SqlUtils.toInt( dr["remaining_time"] ) );
                    item.setLastUsed( SqlUtils.toDateTime( dr["last_used"] ) );
                    item.setBless( SqlUtils.toInt( dr["bless"] ) );
                    item.setAttrEnchantKind( SqlUtils.toInt( dr["attr_enchant_kind"] ) );
                    item.setAttrEnchantLevel( SqlUtils.toInt( dr["attr_enchant_level"] ) );
                    item.getLastStatus().updateAll();
                    items.Add( item );
                }
            }
            return items;
        }

        /// <summary>
        /// プレイヤーにアイテムを追加する。
        /// </summary>
        /// <param name="objId">プレイヤーID</param>
        /// <param name="item">アイテム情報</param>
        public static void storeItem( int objId, L1ItemInstance item )
        {/*TTOK*/
            String sqlstr = @"INSERT INTO character_items SET 
                                id                 = ?1, 
                                item_id            = ?2, 
                                char_id            = ?3, 
                                item_name          = ?4, 
                                count              = ?5, 
                                is_equipped        = 0, 
                                enchantlvl         = ?6, 
                                is_id              = ?7, 
                                durability         = ?8, 
                                charge_count       = ?9, 
                                remaining_time     = ?10, 
                                last_used          = ?11, 
                                bless              = ?12, 
                                attr_enchant_kind  = ?13, 
                                attr_enchant_level = ?14";
            using ( MySqlWrapper wrapper = new MySqlWrapper() )
            {
                MySqlCommand cmd = new MySqlCommand( sqlstr );
                cmd.Parameters.Add( "?1", MySqlDbType.Int24 ).Value = item.getId();
                cmd.Parameters.Add( "?2", MySqlDbType.Int24 ).Value = item.getItem().getItemId();
                cmd.Parameters.Add( "?3", MySqlDbType.Int24 ).Value = objId;
                cmd.Parameters.Add( "?4", MySqlDbType.String ).Value = item.getItem().getName();
                cmd.Parameters.Add( "?5", MySqlDbType.Int24 ).Value = item.getCount();
                cmd.Parameters.Add( "?6", MySqlDbType.Int24 ).Value = item.getEnchantLevel();
                cmd.Parameters.Add( "?7", MySqlDbType.Int24 ).Value = item.isIdentified() ? 1 : 0;
                cmd.Parameters.Add( "?8", MySqlDbType.Int24 ).Value = item.get_durability();
                cmd.Parameters.Add( "?9", MySqlDbType.Int24 ).Value = item.getChargeCount();
                cmd.Parameters.Add( "?10", MySqlDbType.Int24 ).Value = item.getRemainingTime();
                cmd.Parameters.Add( "?11", MySqlDbType.DateTime ).Value = item.getLastUsed();
                cmd.Parameters.Add( "?12", MySqlDbType.Int24 ).Value = item.getBless();
                cmd.Parameters.Add( "?13", MySqlDbType.Int24 ).Value = item.getAttrEnchantKind();
                cmd.Parameters.Add( "?14", MySqlDbType.Int24 ).Value = item.getAttrEnchantLevel();
                wrapper.ExecNonQuery( cmd );
            }

            item.getLastStatus().updateAll();
        }

        /// <summary>
        /// アイテムを削除する。
        /// </summary>
        /// <param name="item">アイテム情報</param>
        public static void deleteItem( L1ItemInstance item )
        {/*TTOK*/
            String sqlstr = "DELETE FROM character_items WHERE id = ?1";
            using ( MySqlWrapper wrapper = new MySqlWrapper() )
            {
                MySqlCommand cmd = new MySqlCommand( sqlstr );
                cmd.Parameters.Add( "?1", MySqlDbType.Int24 ).Value = item.getId();
                wrapper.ExecNonQuery( cmd );
            }
        }

        /// <summary>
        /// 別のアイテムとしてDBに保存する。(便箋を開封したときなどに使用)
        /// </summary>
        /// <param name="item">アイテム情報</param>
        public static void updateItemId( L1ItemInstance item )
        {/*TTOK*/
            String sqlstr = "UPDATE character_items SET item_id = ?1 WHERE id = ?2";
            executeUpdate( item.getId(), sqlstr, item.getItemId() );
            item.getLastStatus().updateItemId();
        }

        /// <summary>
        /// アイテム個数をDBに保存する。
        /// </summary>
        /// <param name="item">アイテム情報</param>
        public static void updateItemCount( L1ItemInstance item )
        {/*TTOK*/
            String sqlstr = "UPDATE character_items SET count = ?1 WHERE id = ?2";
            executeUpdate( item.getId(), sqlstr, item.getCount() );
            item.getLastStatus().updateCount();
        }

        /// <summary>
        /// アイテムの耐久性をDBに保存する。
        /// </summary>
        /// <param name="item">アイテム情報</param>
        public static void updateItemDurability( L1ItemInstance item )
        {/*TTOK*/
            String sqlstr = "UPDATE character_items SET durability = ?1 WHERE id = ?2";
            executeUpdate( item.getId(), sqlstr, item.get_durability() );
            item.getLastStatus().updateDuraility();
        }

        /// <summary>
        /// アイテムのチャージ数をDBに保存する。
        /// </summary>
        /// <param name="item">アイテム情報</param>
        public static void updateItemChargeCount( L1ItemInstance item )
        {/*TTOK*/
            String sqlstr = "UPDATE character_items SET charge_count = ?1 WHERE id = ?2";
            executeUpdate( item.getId(), sqlstr, item.getChargeCount() );
            item.getLastStatus().updateChargeCount();
        }

        /// <summary>
        /// アイテムの使用可能な残り時間をDBに保存する。
        /// </summary>
        /// <param name="item">アイテム情報</param>
        public static void updateItemRemainingTime( L1ItemInstance item )
        {/*TTOK*/
            String sqlstr = "UPDATE character_items SET remaining_time = ?1 WHERE id = ?2";
            executeUpdate( item.getId(), sqlstr, item.getRemainingTime() );
            item.getLastStatus().updateRemainingTime();
        }

        /// <summary>
        /// アイテムの強化数をDBに保存する。
        /// </summary>
        /// <param name="item">アイテム情報</param>
        public static void updateItemEnchantLevel( L1ItemInstance item )
        {/*TTOK*/
            String sqlstr = "UPDATE character_items SET enchantlvl = ?1 WHERE id = ?2";
            executeUpdate( item.getId(), sqlstr, item.getEnchantLevel() );
            item.getLastStatus().updateEnchantLevel();
        }

        /// <summary>
        /// アイテムの装備状態をDBに保存する。
        /// </summary>
        /// <param name="item">アイテム情報</param>
        public static void updateItemEquipped( L1ItemInstance item )
        {/*TTOK*/
            String sqlstr = "UPDATE character_items SET is_equipped = ?1 WHERE id = ?2";
            executeUpdate( item.getId(), sqlstr, ( item.isEquipped() ? 1 : 0 ) );
            item.getLastStatus().updateEquipped();
        }

        /// <summary>
        /// アイテムの鑑定状態をDBに保存する。
        /// </summary>
        /// <param name="item">アイテム情報</param>
        public static void updateItemIdentified( L1ItemInstance item )
        {/*TTOK*/
            String sqlstr = "UPDATE character_items SET is_id = ?1 WHERE id = ?2";
            executeUpdate( item.getId(), sqlstr, ( item.isIdentified() ? 1 : 0 ) );
            item.getLastStatus().updateIdentified();
        }

        /// <summary>
        /// アイテムの効果ディレイをDBに保存する。
        /// </summary>
        /// <param name="item">アイテム情報</param>
        public static void updateItemDelayEffect( L1ItemInstance item )
        {/*TTOK*/
            String sqlstr = "UPDATE character_items SET last_used = ?1 WHERE id = ?2";
            executeUpdate( item.getId(), sqlstr, item.getLastUsed() );
            item.getLastStatus().updateLastUsed();
        }

        /// <summary>
        /// アイテムの祝福・封印状態をDBに保存する。
        /// </summary>
        /// <param name="item">アイテム情報</param>
        public static void updateItemBless( L1ItemInstance item )
        {/*TTOK*/
            String sqlstr = "UPDATE character_items SET bless = ?1 WHERE id = ?2";
            executeUpdate( item.getId(), sqlstr, item.getBless() );
            item.getLastStatus().updateBless();
        }

        /// <summary>
        /// アイテムの属性種類をDBに保存する。
        /// </summary>
        /// <param name="item">アイテム情報</param>
        public static void updateItemAttrEnchantKind( L1ItemInstance item )
        {/*TTOK*/
            String sqlstr = "UPDATE character_items SET attr_enchant_kind = ?1 WHERE id = ?2";
            executeUpdate( item.getId(), sqlstr, item.getAttrEnchantKind() );
            item.getLastStatus().updateAttrEnchantKind();
        }

        /// <summary>
        /// アイテムの属性強化数をDBに保存する。
        /// </summary>
        /// <param name="item">アイテム情報</param>
        public static void updateItemAttrEnchantLevel( L1ItemInstance item )
        {/*TTOK*/
            String sqlstr = "UPDATE character_items SET attr_enchant_level = ?1 WHERE id = ?2";
            executeUpdate( item.getId(), sqlstr, item.getAttrEnchantLevel() );
            item.getLastStatus().updateAttrEnchantLevel();
        }

        /// <summary>
        /// プレイヤーの所持総数を返す。
        /// </summary>
        /// <param name="objId">プレイヤーID</param>
        /// <returns>所持総数</returns>
        public static int getItemCount( int objId )
        {/*TTOK*/
            int count = 0;
            String sqlstr = "SELECT * FROM character_items WHERE char_id = ?1";
            using ( MySqlWrapper wrapper = new MySqlWrapper() )
            {
                MySqlCommand cmd = new MySqlCommand( sqlstr );
                cmd.Parameters.Add( "?1", MySqlDbType.Int24 ).Value = objId;
                Object obj = wrapper.ExecScaler( cmd );
                if ( obj != null && !( obj is DBNull ) )
                {
                    count = Convert.ToInt32( obj );
                }
                //DataTable dt = wrapper.GetDataTable( cmd );
                //foreach ( DataRow item in dt.Rows )
                //{
                //    count++;
                //}
            }
            return count;
        }

        /// <summary>
        /// アイテム情報をDB更新する。
        /// </summary>
        /// <param name="objId">アイテムID</param>
        /// <param name="sql">SQL文</param>
        /// <param name="updateNum">更新する値</param>
        private static void executeUpdate( int objId, String sql, int updateNum )
        {/*TTOK*/
            using ( MySqlWrapper wrapper = new MySqlWrapper() )
            {
                MySqlCommand cmd = new MySqlCommand( sql );
                cmd.Parameters.Add( "?1", MySqlDbType.Int24 ).Value = updateNum;
                cmd.Parameters.Add( "?2", MySqlDbType.Int24 ).Value = objId;
                wrapper.ExecNonQuery( cmd );
            }
        }

        /// <summary>
        /// アイテム情報をDB更新する。
        /// </summary>
        /// <param name="objId">アイテムID</param>
        /// <param name="sql">SQL文</param>
        /// <param name="ts">更新する値</param>
        private static void executeUpdate( int objId, String sql, Nullable<DateTime> ts )
        {/*TTOK*/
            using ( MySqlWrapper wrapper = new MySqlWrapper() )
            {
                MySqlCommand cmd = new MySqlCommand( sql );
                cmd.Parameters.Add( "?1", MySqlDbType.DateTime ).Value = ts;
                cmd.Parameters.Add( "?2", MySqlDbType.Int24 ).Value = objId;
                wrapper.ExecNonQuery( cmd );
            }
        }
    }
}
